#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <iostream>
#include <time.h>
#include <string.h>
#include <vector>
#include <array>
#include <string>
#include <fstream>
#include <map>
#include <unordered_map>
#include <set>
#include <list>
#include <condition_variable>
#include <mutex>
#include <algorithm>
#define PLATFORM_LITTLE_ENDIAN 1
#if (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
	#define PLATFORM_CPU_ARM_FAMILY							1
	#define PLATFORM_ENABLE_VECTORINTRINSICS_NEON			1
	#define PLATFORM_ENABLE_VECTORINTRINSICS				1
#elif (defined(_M_IX86) || defined(_M_X64))
	#define PLATFORM_CPU_ARM_FAMILY							0
	#define PLATFORM_CPU_X86_FAMILY							1

#endif
//ALICE_IPHONE,ALICE_ANDROID,ALICE_WINDOWS{_Player|Editor},ALICE_OSX{_Player|Editor}
//ALICE_OGL,ALICE_OGLES,ALICE_D3D12,ALICE_D3D11,ALICE_VULKAN,ALICE_METAL,ALICE_WEBGPU
//ALICE_LUA_PORT,ALICE_JS_CEF_PORT,ALICE_JS_V8_PORT
#if defined(_WIN64) || defined(_WIN32)
#define ALICE_WINDOWS 1
#endif

template<typename T32BITS, typename T64BITS, int PointerSize>
struct PointerType{};
template<typename T32BITS, typename T64BITS>
struct PointerType<T32BITS, T64BITS, 8>{
	typedef T64BITS TIntPointer;
};
template<typename T32BITS, typename T64BITS>
struct PointerType<T32BITS, T64BITS, 4>{
	typedef T32BITS TIntPointer;
};
struct BasicPlatformTypes
{
	typedef unsigned char 		uint8;
	typedef unsigned short int	uint16;
	typedef unsigned int		uint32;
	typedef unsigned long long	uint64;
	typedef	signed char			int8;
	typedef signed short int	int16;
	typedef signed int	 		int32;
	typedef signed long long	int64;
	typedef char				ANSICHAR;
	typedef wchar_t				WIDECHAR;
	typedef uint8				CHAR8;
	typedef uint16				CHAR16;
	typedef uint32				CHAR32;
	typedef WIDECHAR			TCHAR;
	typedef PointerType<uint32, uint64, sizeof(void*)>::TIntPointer UINTPTR;
	typedef PointerType<int32, int64, sizeof(void*)>::TIntPointer INTPTR;
	typedef UINTPTR SIZE_T;
	typedef INTPTR SSIZE_T;
	typedef int32					TYPE_OF_NULL;
	typedef decltype(nullptr)		TYPE_OF_NULLPTR;
};
struct WindowsPlatformTypes : public BasicPlatformTypes
{
#ifdef _WIN64
	typedef unsigned __int64	SIZE_T;
	typedef __int64				SSIZE_T;
#else
	typedef unsigned long		SIZE_T;
	typedef long				SSIZE_T;
#endif
};
typedef WindowsPlatformTypes PlatformTypes;

#ifndef EMIT_CUSTOM_WARNING
#define EMIT_CUSTOM_WARNING(Warning) \
		EMIT_CUSTOM_WARNING_AT_LINE(__LINE__, Warning)
#endif

#ifndef DEPRECATED_MACRO
#define DEPRECATED_MACRO(Version, Message) EMIT_CUSTOM_WARNING(Message " Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.")
#endif

#define DEPRECATED DEPRECATED_MACRO
typedef PlatformTypes::uint8		uint8;
typedef PlatformTypes::uint16		uint16;
typedef PlatformTypes::uint32		uint32;
typedef PlatformTypes::uint64		uint64;
typedef	PlatformTypes::int8		    int8;
typedef PlatformTypes::int16		int16;
typedef PlatformTypes::int32		int32;
typedef PlatformTypes::int64		int64;
typedef PlatformTypes::ANSICHAR	    ANSICHAR;
typedef PlatformTypes::WIDECHAR	    WIDECHAR;
#ifdef ALICE_WINDOWS
#else
typedef PlatformTypes::TCHAR		TCHAR;
#endif
typedef PlatformTypes::CHAR8		UTF8CHAR;
typedef PlatformTypes::CHAR16		UCS2CHAR;
typedef PlatformTypes::CHAR16		UTF16CHAR;
typedef PlatformTypes::CHAR32		UTF32CHAR;
typedef PlatformTypes::UINTPTR      UPTRINT;
typedef PlatformTypes::INTPTR       PTRINT;
typedef PlatformTypes::SIZE_T       SIZE_T;
typedef PlatformTypes::SSIZE_T      SSIZE_T;
typedef PlatformTypes::TYPE_OF_NULL	TYPE_OF_NULL;
typedef PlatformTypes::TYPE_OF_NULLPTR	TYPE_OF_NULLPTR;

#define MIN_uint8		((uint8)	0x00)
#define	MIN_uint16		((uint16)	0x0000)
#define	MIN_uint32		((uint32)	0x00000000)
#define MIN_uint64		((uint64)	0x0000000000000000)
#define MIN_int8		((int8)		-128)
#define MIN_int16		((int16)	-32768)
#define MIN_int32		((int32)	0x80000000)
#define MIN_int64		((int64)	0x8000000000000000)

#define MAX_uint8		((uint8)	0xff)
#define MAX_uint16		((uint16)	0xffff)
#define MAX_uint32		((uint32)	0xffffffff)
#define MAX_uint64		((uint64)	0xffffffffffffffff)
#define MAX_int8		((int8)		0x7f)
#define MAX_int16		((int16)	0x7fff)
#define MAX_int32		((int32)	0x7fffffff)
#define MAX_int64		((int64)	0x7fffffffffffffff)

#define MIN_flt			(1.175494351e-38F)
#define MAX_flt			(3.402823466e+38F)
#define MIN_dbl			(2.2250738585072014e-308)
#define MAX_dbl			(1.7976931348623158e+308)

#define ALICE_DELTA		(0.00001f)
#define ALICE_PI 					(3.1415926535897932f)	/* Extra digits if needed: 3.1415926535897932384626433832795f */
#define ALICE_SMALL_NUMBER			(1.e-8f)
#define ALICE_KINDA_SMALL_NUMBER	(1.e-4f)
#define ALICE_BIG_NUMBER			(3.4e+38f)
#define ALICE_EULERS_NUMBER		(2.71828182845904523536f)
#define ALICE_GOLDEN_RATIO			(1.6180339887498948482045868343656381f)	/* Also known as divine proportion, golden mean, or golden section - related to the Fibonacci Sequence = (1 + sqrt(5)) / 2 */
#define ALICE_FLOAT_NON_FRACTIONAL (8388608.f) /* All single-precision floating point numbers greater than or equal to this have no fractional value. */


#define ALICE_DOUBLE_PI					(3.141592653589793238462643383279502884197169399)
#define ALICE_DOUBLE_SMALL_NUMBER			(1.e-8)
#define ALICE_DOUBLE_KINDA_SMALL_NUMBER	(1.e-4)
#define ALICE_DOUBLE_BIG_NUMBER			(3.4e+38)
#define ALICE_DOUBLE_EULERS_NUMBER			(2.7182818284590452353602874713526624977572)
#define ALICE_DOUBLE_GOLDEN_RATIO			(1.6180339887498948482045868343656381)	/* Also known as divine proportion, golden mean, or golden section - related to the Fibonacci Sequence = (1 + sqrt(5)) / 2 */
#define ALICE_DOUBLE_NON_FRACTIONAL		(4503599627370496.0) /* All double-precision floating point numbers greater than or equal to this have no fractional value. 2^52 */

#define ALICE_THRESH_SPLIT_POLY_WITH_PLANE			(0.25f)		/* A plane splits a polygon in half */
#define ALICE_THRESH_SPLIT_POLY_PRECISELY			(0.01f)		/* A plane exactly splits a polygon */
#define ALICE_THRESH_ZERO_NORM_SQUARED				(0.0001f)	/* Size of a unit normal that is considered "zero", squared */
#define ALICE_THRESH_NORMALS_ARE_PARALLEL			(0.999845f)	/* Two unit vectors are parallel if abs(A dot B) is greater than or equal to this. This is roughly cosine(1.0 degrees). */
#define ALICE_THRESH_NORMALS_ARE_ORTHOGONAL		(0.017455f)	/* Two unit vectors are orthogonal (perpendicular) if abs(A dot B) is less than or equal this. This is roughly cosine(89.0 degrees). */

class Noncopyable{
protected:
	Noncopyable() {}
	~Noncopyable() {}
private:
	Noncopyable(const Noncopyable&);
	Noncopyable& operator=(const Noncopyable&);
};

#define PLATFORM_CACHE_LINE_SIZE 64
//#define ALICE_DEPRECATED __declspec(deprecated)
#define ALICE_DEPRECATED(...)
#if defined(__GNUC__)
#define ALIGN_OF(T) __alignof__(T)
#define ALIGN_TYPE(val) __attribute__((aligned(val)))
#define FORCE_INLINE inline __attribute__ ((always_inline))
#elif defined(_MSC_VER)
#define ALIGN_OF(T) __alignof(T)
#define ALIGN_TYPE(val) __declspec(align(val))
#define FORCE_INLINE __forceinline
#else
#define ALIGN_TYPE(size)
#define FORCE_INLINE inline
#endif
#define MS_ALIGN(n)
#define GCC_ALIGN(n)
#define INDEX_NONE -1
#if ALICE_IPHONE || ALICE_OSX_PLAYER
#define ALICE_PLATFORM_APPLE 1
#endif
#if ALICE_ANDROID
#define ALICE_PLATFORM_ANDROID 1
#endif
//types
#if ALICE_IPHONE || ALICE_ANDROID
#define _MAX_PATH 256
#define ALICE_PLATFORM_MOBILE 1
#endif

template<int32 Size, uint32 Alignment>
struct TAlignedBytes;

template<int32 Size>
struct TAlignedBytes<Size, 1>
{
	uint8 Pad[Size];
};
#define IMPLEMENT_ALIGNED_STORAGE(Align) \
template<int32 Size>        \
struct TAlignedBytes<Size,Align> \
{ \
	struct MS_ALIGN(Align) TPadding \
	{ \
		uint8 Pad[Size]; \
	} GCC_ALIGN(Align); \
	TPadding Padding; \
};
IMPLEMENT_ALIGNED_STORAGE(16);
IMPLEMENT_ALIGNED_STORAGE(8);
IMPLEMENT_ALIGNED_STORAGE(4);
IMPLEMENT_ALIGNED_STORAGE(2);
#undef IMPLEMENT_ALIGNED_STORAGE

template<typename ElementType>
struct TTypeCompatibleBytes :
	public TAlignedBytes<
	sizeof(ElementType),
	alignof(ElementType)
	>
{
	ElementType* GetTypedPtr() { return (ElementType*)this; }
	const ElementType* GetTypedPtr() const { return (const ElementType*)this; }
};
#define ENUM_CLASS_FLAGS(Enum) \
	inline           Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
	inline           Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
	inline           Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
	inline constexpr Enum  operator| (Enum  Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
	inline constexpr Enum  operator& (Enum  Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
	inline constexpr Enum  operator^ (Enum  Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
	inline constexpr bool  operator! (Enum  E)             { return !(__underlying_type(Enum))E; } \
	inline constexpr Enum  operator~ (Enum  E)             { return (Enum)~(__underlying_type(Enum))E; }
// Friends all bitwise operators for enum classes so the definition can be kept private / protected.
#define FRIEND_ENUM_CLASS_FLAGS(Enum) \
	friend           Enum& operator|=(Enum& Lhs, Enum Rhs); \
	friend           Enum& operator&=(Enum& Lhs, Enum Rhs); \
	friend           Enum& operator^=(Enum& Lhs, Enum Rhs); \
	friend constexpr Enum  operator| (Enum  Lhs, Enum Rhs); \
	friend constexpr Enum  operator& (Enum  Lhs, Enum Rhs); \
	friend constexpr Enum  operator^ (Enum  Lhs, Enum Rhs); \
	friend constexpr bool  operator! (Enum  E); \
	friend constexpr Enum  operator~ (Enum  E);

template<typename Enum>
constexpr bool EnumHasAllFlags(Enum Flags, Enum Contains)
{
	using UnderlyingType = __underlying_type(Enum);
	return ((UnderlyingType)Flags & (UnderlyingType)Contains) == (UnderlyingType)Contains;
}

template<typename Enum>
constexpr bool EnumHasAnyFlags(Enum Flags, Enum Contains)
{
	using UnderlyingType = __underlying_type(Enum);
	return ((UnderlyingType)Flags & (UnderlyingType)Contains) != 0;
}

template<typename Enum>
void EnumAddFlags(Enum& Flags, Enum FlagsToAdd)
{
	using UnderlyingType = __underlying_type(Enum);
	Flags = (Enum)((UnderlyingType)Flags | (UnderlyingType)FlagsToAdd);
}

template<typename Enum>
void EnumRemoveFlags(Enum& Flags, Enum FlagsToRemove)
{
	using UnderlyingType = __underlying_type(Enum);
	Flags = (Enum)((UnderlyingType)Flags & ~(UnderlyingType)FlagsToRemove);
}
#ifdef __clang__
	#define ALICE_PUSH_MACRO(name) _Pragma(PREPROCESSOR_TO_STRING(push_macro(name)))
	#define ALICE_POP_MACRO(name) _Pragma(PREPROCESSOR_TO_STRING(pop_macro(name)))
#else
	#define ALICE_PUSH_MACRO(name) __pragma(push_macro(name))
	#define ALICE_POP_MACRO(name) __pragma(pop_macro(name))
#endif
enum EForceInit 
{
	ForceInit,
	ForceInitToZero
};
enum ENoInit {NoInit};
enum EInPlace {InPlace};
enum EPerElement {PerElement};
#ifdef __clang__
#define STRUCT_OFFSET( struc, member )	__builtin_offsetof(struc, member)
#else
#define STRUCT_OFFSET( struc, member )	offsetof(struc, member)
#endif
#ifdef ALICE_WINDOWS
#include <WinSock2.h>
#include <windows.h>
#include <intrin.h>
#include <WinNls.h>
#include <wchar.h>
#include <tchar.h>
#include <io.h>
#include <direct.h>
#include <ShlObj.h>
#include <ShObjIdl.h>
#include <shellapi.h>
#define bswap_32(x) _byteswap_ulong(x)
#define bswap_64(x) _byteswap_uint64(x)
#elif defined(ALICE_OSX_PLAYER) || defined(ALICE_ANDROID) || defined(ALICE_IPHONE)
#define ALICE_PLATFORM_UNIX 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <net/if.h>
#include <pthread.h>
#include <dirent.h>
#ifdef ALICE_IPHONE
#include <ifaddrs.h>
#define ALICE_MOBILE 1
#endif
#ifdef ALICE_ANDROID
#define ALICE_MOBILE 1
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/native_window_jni.h>
#include <dirent.h>
#define JAVA_API(return_type) extern "C" JNIEXPORT return_type JNICALL
#define JFOO(CLS,METHOD) Java_com_alice_battlefire_androidplayer_##CLS##_##METHOD
#if defined(__arm64__)||defined(__aarch64__)
#define ANDROID_ARCH "arm64-v8a"
#elif defined(__arm__)
#define ANDROID_ARCH "armeabi-v7a"
#else
#define ANDROID_ARCH "Unkown"
#endif
#endif
#endif
#include <string>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <thread>
#include <mutex>
#include <condition_variable>
typedef signed char AliceSInt8;
typedef unsigned char AliceUInt8;
typedef AliceUInt8 AliceUByte;
typedef AliceSInt8 AliceByte;
typedef signed short AliceSInt16;
typedef unsigned short AliceUInt16;
typedef int AliceSInt32;
typedef unsigned int AliceUInt32;
typedef unsigned long long AliceUInt64;
typedef signed long long AliceSInt64;
typedef AliceSInt32 LuaScriptHandle;
typedef void* AliceAny;
#ifndef _MAX_PATH
#define _MAX_PATH 260
#endif
#if ALICE_PLATFORM_WIN
#define ALICE_STRICMP _stricmp 
#else 
#define ALICE_STRICMP strcasecmp
#endif
#define _00000000_00000000_00000000_00000001 1
#define _00000000_00000000_00000000_00000010 2
#define _00000000_00000000_00000000_00000100 4
#define _00000000_00000000_00000000_00001000 8
#define _00000000_00000000_00000000_00010000 16
#define _00000000_00000000_00000000_00100000 32
#define _00000000_00000000_00000000_01000000 64
#define _00000000_00000000_00000000_10000000 128
#define _00000000_00000000_00000001_00000000 256
#define _00000000_00000000_00000010_00000000 512
#define _00000000_00000000_00000100_00000000 1024
#define _00000000_00000000_00001000_00000000 2048
#define _00000000_00000000_00010000_00000000 4096
#define _00000000_00000000_00100000_00000000 8192
#define _00000000_00000000_01000000_00000000 16384
#define _00000000_00000000_10000000_00000000 32768
#define _00000000_00000001_00000000_00000000 65536
#define _00000000_00000010_00000000_00000000 131072
#define _00000000_00000100_00000000_00000000 262144
#define _00000000_00001000_00000000_00000000 524288
#define _00000000_00010000_00000000_00000000 1048576
#define _00000000_00100000_00000000_00000000 2097152
#define _00000000_01000000_00000000_00000000 4194304
#define _00000000_10000000_00000000_00000000 8388608
#define _00000001_00000000_00000000_00000000 16777216
#define _00000010_00000000_00000000_00000000 33554432
#define _00000100_00000000_00000000_00000000 67108864
#define _00001000_00000000_00000000_00000000 134217728
#define _00010000_00000000_00000000_00000000 268435456
#define _00100000_00000000_00000000_00000000 536870912
#define _01000000_00000000_00000000_00000000 1073741824
#define _10000000_00000000_00000000_00000000 2147483648
typedef void(*VOID_VOID_PTR)(void*);
#define ALICE_PTRDIFF_TO_INT32(argument) static_cast<int32>(argument)
#define ALICE_PTRDIFF_TO_UINT32(argument) static_cast<uint32>(argument)


/**
 * Aligns a value to the nearest higher multiple of 'Alignment', which must be a power of two.
 *
 * @param  Val        The value to align.
 * @param  Alignment  The alignment value, must be a power of two.
 *
 * @return The value aligned up to the specified alignment.
 */
template <typename T>
FORCEINLINE constexpr T Align(T Val, uint64 Alignment)
{
	return (T)(((uint64)Val + Alignment - 1) & ~(Alignment - 1));
}

/**
 * Aligns a value to the nearest lower multiple of 'Alignment', which must be a power of two.
 *
 * @param  Val        The value to align.
 * @param  Alignment  The alignment value, must be a power of two.
 *
 * @return The value aligned down to the specified alignment.
 */
template <typename T>
FORCEINLINE constexpr T AlignDown(T Val, uint64 Alignment)
{
	return (T)(((uint64)Val) & ~(Alignment - 1));
}

/**
 * Checks if a pointer is aligned to the specified alignment.
 *
 * @param  Val        The value to align.
 * @param  Alignment  The alignment value, must be a power of two.
 *
 * @return true if the pointer is aligned to the specified alignment, false otherwise.
 */
template <typename T>
FORCEINLINE constexpr bool IsAligned(T Val, uint64 Alignment)
{
	return !((uint64)Val & (Alignment - 1));
}

/**
 * Aligns a value to the nearest higher multiple of 'Alignment'.
 *
 * @param  Val        The value to align.
 * @param  Alignment  The alignment value, can be any arbitrary value.
 *
 * @return The value aligned up to the specified alignment.
 */
template <typename T>
FORCEINLINE constexpr T AlignArbitrary(T Val, uint64 Alignment)
{
	return (T)((((uint64)Val + Alignment - 1) / Alignment) * Alignment);
}

#define check(x)
#define checkSlow(x)
#define checkf(x)
#define checkNoEntry()
#define ensure(x)
#define UMETA(x)
#define ensureMsgf(x)
